/*
============================================================================
 Name        : PodcastUI.cpp
 Author      : 
 Version     :
 Copyright   : Your copyright notice
 Description : CPodcastUI implementation
============================================================================
*/

#include "PodcastUI.h"
#include "PodcastPlugin.h"
#include "Podcast.mbg"
#include "PluginUtility.h"
#include "RssFeed.h"
#include "Ticker.h"

#include <eikenv.h>			//CEikonEnv
#include <fbs.h>			//CFbsBitmap

//Colors
#define SHADOW_COLOR TRgb(0x555555)
#define SELECTED_BACK_COLOR TRgb(0xffaea5)
#define SELECTED_FONT_COLOR TRgb(0x6f1032)

//List rectangle
#define ITEM_WIDTH (iTextWidth - 2)

//Bitmap indexes
#define BITMAP_PLAY (TInt)EMbmPodcastPlay
#define BITMAP_PLAY_MASK (TInt)EMbmPodcastPlay_mask
#define BITMAP_BUFFERING (TInt)EMbmPodcastBuffering
#define BITMAP_BUFFERING_MASK (TInt)EMbmPodcastBuffering_mask
#define BITMAP_STOP (TInt)EMbmPodcastStop
#define BITMAP_STOP_MASK (TInt)EMbmPodcastStop_mask
#define BITMAP_ERROR (TInt)EMbmPodcastError
#define BITMAP_ERROR_MASK (TInt)EMbmPodcastError_mask


//Mbm filename
_LIT(KPodcastMbmFileName, "podcast.mbm");


CPodcastUI::CPodcastUI()
: iContainer(NULL), iTitle(NULL), iItem(NULL), iFontHeight(CEikonEnv::Static()->NormalFont()->HeightInPixels()),
iTextWidth(0), iMaxNumItems(0), iIsBuffering(EFalse), iPercent(-1), iImageHandler(NULL), iImage(NULL), 
iIsPlaying(EFalse), iImageIsReady(EImagePending)
{
}

CPodcastUI::~CPodcastUI()
{
	DELETE(iTitle);
	DELETE(iItem);
	DELETE(iImageHandler);
	DELETE(iImage);

	//Delete bitmaps
	iBitmaps.ResetAndDestroy();
}

CPodcastUI* CPodcastUI::NewLC()
{
	CPodcastUI* self = new (ELeave)CPodcastUI();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
}

CPodcastUI* CPodcastUI::NewL()
{
	CPodcastUI* self=CPodcastUI::NewLC();
	CleanupStack::Pop(); // self;
	return self;
}

void CPodcastUI::ConstructL()
{
	//Load bitmaps
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_PLAY));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_PLAY_MASK));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_BUFFERING));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_BUFFERING_MASK));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_STOP));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_STOP_MASK));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_ERROR));
	iBitmaps.Append(CPluginUtility::CreateBitmapL(KPodcastMbmFileName, BITMAP_ERROR_MASK));
}

void CPodcastUI::ImageIsReady(TInt aError)
{
	if (aError)
	{
		iImageIsReady = EImageFailed;
	}
	else
	{
		iImageIsReady = EImageReady;

		//Set bitmap size
		iImageSize = iImage->SizeInPixels();
	}

	//Set ticker text
	SetTickerText(GetSelectedItem()->Description());

	//Request completed
	iOnFinishCallback->CallBack();
}

void CPodcastUI::SelectNextItem()
{
	SelectItem(ETrue);
}

void CPodcastUI::SelectPreviousItem()
{
	SelectItem(EFalse);
}

void CPodcastUI::SelectItem(TBool aNextItem)
{
	if (!iRssFeed) return;

	if (aNextItem)
	{
		//Next item
		TInt numItems = iRssFeed->GetItems().Count();
		if (iSelectedIndex >= numItems - 1) return;
		iSelectedIndex++;
		if (iSelectedIndex - iTopIndex >= iMaxNumItems) iTopIndex++;
	}
	else
	{
		//Previous item
		if (iSelectedIndex <= 0) return;
		iSelectedIndex--;
		if (iSelectedIndex < iTopIndex) iTopIndex = iSelectedIndex;
	}
	
	//Refresh item ticker
	iItem->SetText(GetSelectedItem()->Title(), ITEM_WIDTH);

	//Set ticker text
	SetTickerText(GetSelectedItem()->Description());

	//Repaint
	iContainer->Repaint();
}

void CPodcastUI::SetContainer(MPluginContainer* aContainer) 
{ 
	iContainer = aContainer; 

	//Recreate tickers
	DELETE(iTitle);
	iTitle = CTicker::NewL(iContainer);

	DELETE(iItem);
	iItem = CTicker::NewL(iContainer);
}

void CPodcastUI::Draw(CWindowGc& aGc, const TRect& aRect) const
{
	TInt *piTextWidth;
	piTextWidth = CONST_CAST(TInt*, &iTextWidth);
	*piTextWidth = aRect.iBr.iX - aRect.iTl.iY - 12;

	//Calculate max size for image
	if (!iImageMaxSize.iWidth && !iImageMaxSize.iHeight)
	{
		TSize* piImageMaxSize;
		piImageMaxSize = CONST_CAST(TSize*, &iImageMaxSize);
		*piImageMaxSize = aRect.Size() - TPoint(4, 4); 
	}

	if (!iRssFeed) return;

	if (iIsPlaying)
	{
		//Draw image
		if (iImageIsReady == EImageReady)
		{
			TPoint p = aRect.iTl + TPoint((aRect.Width() - iImageSize.iWidth) >> 1, (aRect.Height() - iImageSize.iHeight) >> 1);

			//Draw shadow
			aGc.SetPenColor(BackShadowColor());
			aGc.DrawRect(TRect(p, p + iImageSize + TPoint(2, 2)));

			//Draw border
			aGc.SetPenColor(BackBorderColor());
			aGc.DrawRect(TRect(p + TPoint(-1, -1), p + iImageSize + TPoint(1, 1)));

			//Draw image
			aGc.BitBlt(p, iImage);
		}
	}
	else
	{
		//Draw title
		aGc.SetPenColor(KRgbWhite);
		aGc.DrawText(iTitle->GetText(), TPoint(aRect.iTl.iX + 1, aRect.iTl.iY + iFontHeight + 2));
		
		aGc.SetPenColor(ForeColor());
		aGc.DrawText(iTitle->GetText(), TPoint(aRect.iTl.iX, aRect.iTl.iY + iFontHeight + 1));

		//Draw frame
		aGc.SetPenColor(InsideBorderColor());
		TRect frameRect(aRect.iTl.iX + 1, aRect.iTl.iY + iFontHeight + 6, aRect.iBr.iX - 1, aRect.iBr.iY - 1);
		aGc.DrawRoundRect(frameRect, TSize(2, 2));

		//Reduce frame to list
		frameRect.iTl.iX += 2;
		frameRect.iTl.iY += 2;
		frameRect.iBr.iX -= 2;
		frameRect.iBr.iY -= 2;

		//Calculate item width
		TInt itemWidth = frameRect.iBr.iX - frameRect.iTl.iX;
		TInt itemHeight = iFontHeight + 2;
		
		TInt *piMaxNumItems;
		piMaxNumItems = CONST_CAST(int*, &iMaxNumItems);
		*piMaxNumItems = (frameRect.iBr.iY - frameRect.iTl.iY) / (itemHeight + 1);

		//Draw list
		TInt numItems = iRssFeed->GetItems().Count();

		TInt num = 0; 
		TInt top = (numItems > iMaxNumItems ? iMaxNumItems : numItems);
		TInt index;
		
		TRect itemRect(frameRect.iTl.iX, frameRect.iTl.iY, frameRect.iBr.iX, frameRect.iTl.iY + itemHeight);
		while (num < top)
		{
			TInt baseline = ((itemRect.Height() + CEikonEnv::Static()->NormalFont()->AscentInPixels()) >> 1); 

			index = iTopIndex + num;
			if (index == iSelectedIndex)
			{
				//Draw shadow
				aGc.SetBrushColor(SHADOW_COLOR);
				aGc.SetPenColor(SHADOW_COLOR);
				aGc.DrawRect(TRect(itemRect.iTl + TPoint(1, 1), itemRect.iBr + TPoint(1, 1)));

				//Set selected colors
				aGc.SetBrushColor(SELECTED_BACK_COLOR);
				aGc.SetPenColor(SELECTED_FONT_COLOR);

				//Draw text
				aGc.DrawText(iItem->GetText(), itemRect, baseline, CGraphicsContext::ELeft, 1);
			}
			else
			{
				//Set normal color
				aGc.SetBrushColor(InsideColor());
				aGc.SetPenColor(ForeColor());

				//Draw text
				aGc.DrawText(iRssFeed->GetItems()[index]->Title(), itemRect, baseline, CGraphicsContext::ELeft, 1);
			}

			//Next item
			itemRect.iTl.iY += (itemHeight + 1);
			itemRect.iBr.iY += (itemHeight + 1);
			num++;
		}
	}
}

void CPodcastUI::SetTickerIcon(TPodcastTickerIcon aIcon)
{
	TInt index, indexMask;

	switch (aIcon)
	{
	case EPlay:
		index = BITMAP_PLAY;
		indexMask = BITMAP_PLAY_MASK;
		break;

	case EBuffering:
		index = BITMAP_BUFFERING;
		indexMask = BITMAP_BUFFERING_MASK;
		break;

	case EStop:
		index = BITMAP_STOP;
		indexMask = BITMAP_STOP_MASK;
		break;

	case EError:
		index = BITMAP_ERROR;
		indexMask = BITMAP_ERROR_MASK;

	default:
		iContainer->SetTickerIcon(NULL, NULL);
		return;
	}
	iContainer->SetTickerIcon(iBitmaps[index], iBitmaps[indexMask]);
}

void CPodcastUI::SetTickerText(const TDesC& aText)
{
	iContainer->SetTickerText(aText);
}

void CPodcastUI::SetTickerTextFormat(TRefByValue<const TDesC16> aFmt, ...)
{
	iContainer->SetTickerTextFormat(aFmt);
}

void CPodcastUI::SetIsBuffering(TBool aIsBuffering, TInt aPercent) 
{ 
	if (aIsBuffering == iIsBuffering && aPercent == iPercent) return;
	
	//Save state and percent
	iIsBuffering = aIsBuffering;
	iPercent = aPercent;

	//Icon
	SetTickerIcon(iIsBuffering ? EBuffering : EPlay);

	//Text
	if (iIsBuffering)
	{
		TBuf<22> buf;
		buf.AppendFormat(_L("Buffering %d%% ..."), iPercent);
		SetTickerText(buf);
	}
	else
	{
		SetTickerText(_L("Playing ..."));
	}

	//Repaint
	iContainer->Repaint();
}

void CPodcastUI::SetRssFeed(TRssFeed* aRssFeed) 
{ 
	iRssFeed = aRssFeed;

	//Selected item
	iTopIndex = 0;
	iSelectedIndex = 0;

	//Set ticker texts
	iTitle->SetText(iRssFeed->Title(), iTextWidth);
	
	TRssFeedItem* selectedItem = GetSelectedItem();
	if (selectedItem) iItem->SetText(selectedItem->Title(), ITEM_WIDTH);
}

void CPodcastUI::SetImageUrl(const TDesC& aImageUrl, TCallBack& aOnFinishCallback)
{
	//Set callback
	iOnFinishCallback = &aOnFinishCallback;

	//Reset bitmap
	iImageIsReady = EImagePending;
	DELETE(iImage);
	iImage = new (ELeave)CFbsBitmap;

	RDebug::Print(aImageUrl);

	//Convert and resize image
	DELETE(iImageHandler);
	iImageHandler = CImageHandler::NewL(*iImage, *this);
	iImageHandler->GetAndConvertL(aImageUrl, iImageMaxSize);
}

TRssFeedItem* CPodcastUI::GetSelectedItem()
{
	if (iRssFeed->GetItems().Count() == 0) return NULL;
	return iRssFeed->GetItems()[iSelectedIndex];
}

void CPodcastUI::Activate()
{
	//Clear container ticker
	iContainer->SetTickerIcon(NULL, NULL);
	iContainer->SetTickerText(_L(""));

	//Activate tickers
	iTitle->Activate();
	iItem->Activate();
}

void CPodcastUI::Deactivate()
{
	iTitle->Deactivate();
	iItem->Deactivate();
}
